package com.xiaoshu.disruptor.handler;

import com.lmax.disruptor.EventHandler;
import com.xiaoshu.disruptor.MessageEvent;
import com.xiaoshu.disruptor.MethodInfoModel;
import com.xiaoshu.service.BaseDoubleWriteRedisTemplate;
import com.xiaoshu.service.SlaveDoubleWriteRedisTemplate;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * code is far away from bug with the animal protecting
 * ┏┓　　　┏┓
 * ┏┛┻━━━┛┻┓
 * ┃　　　　　　　┃
 * ┃　　　━　　　┃
 * ┃　┳┛　┗┳　┃
 * ┃　　　　　　　┃
 * ┃　　　┻　　　┃
 * ┃　　　　　　　┃
 * ┗━┓　　　┏━┛
 * 　　┃　　　┃神兽保佑
 * 　　┃　　　┃代码无BUG！
 * 　　┃　　　┗━━━┓
 * 　　┃　　　　　　　┣┓
 * 　　┃　　　　　　　┏┛
 * 　　┗┓┓┏━┳┓┏┛
 * 　　　┃┫┫　┃┫┫
 * 　　　┗┻┛　┗┻┛
 *
 * @Description : function description
 * ---------------------------------
 * @Author : deane
 * @Date : Create in 2021/3/20 10:31
 * <p>
 * Copyright (C)2013-2021 小树盛凯科技 All rights reserved.
 */
@Component
@Slf4j
public class HandlerMethodEvent implements EventHandler<MessageEvent> {

    ExecutorService executorService = Executors.newSingleThreadExecutor();

    BaseDoubleWriteRedisTemplate slaveDoubleWriteRedisTemplate;

    @Autowired
    @Qualifier(value = "slaveDoubleWriteRedisTemplate")
    public void setSlaveDoubleWriteRedisTemplate(SlaveDoubleWriteRedisTemplate slaveDoubleWriteRedisTemplate) {
        this.slaveDoubleWriteRedisTemplate = slaveDoubleWriteRedisTemplate;
    }

    @Override
    @SneakyThrows
    public void onEvent(MessageEvent messageEvent,  long sequence, boolean endOfBatch) throws Exception {
        MethodInfoModel methodInfo = messageEvent.getMethodInfo();
        Method method = methodInfo.getMethod();
        executorService.execute(()->{
            try {
                log.info("[Disruptor handler] method : {} event :{}", method.getName(), messageEvent.toString());
                // find the same method from slaveDoubleWriteRedisTemplate; then invoke the method;
                Method reflectMethod = ReflectionUtils.findMethod(slaveDoubleWriteRedisTemplate.getClass(), method.getName(), method.getParameterTypes());
                if(!ObjectUtils.isEmpty(reflectMethod)){
                   reflectMethod.invoke(slaveDoubleWriteRedisTemplate, methodInfo.getParameters());
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        });
    }
}
